import org.junit.Test;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

/**
 * 一、使用NIO 完成网络通信的三个核心：
 *
 * 1、通道(Channel):负责连接
 *      java.nio.channels.Channel 接口：
 *           |--SelectableChannel
 *               |--SocketChannel
 *               |--ServerSocketChannel
 *               |--DatagramChannel
 *
 *               |--Pipe.SinkChannel
 *               |--Pipe.SourceChannel
 *
 * 2.缓冲区(Buffer):负责数据的存取
 *
 * 3.选择器(Selector):是 SelectableChannel 的多路复用器。用于监控SelectableChannel的IO状况
 */
public class TestBlockingNIO {

    //客户端
    @Test
    public void client(){
        SocketChannel sChannel = null;
        FileChannel open = null;
        try {
            //1.获取通道
            sChannel  = SocketChannel.open(new InetSocketAddress("127.0.0.1",9999));
            //2.分配指定大小的缓冲区
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            //3.读取文件,并发送到服务器
             open = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
            while (open.read(buffer) != -1) {
                buffer.flip(); //切换读写状态
                sChannel.write(buffer);
                buffer.clear();
            }
            sChannel.shutdownOutput();//关闭发送通道，表明发送完毕
            //4.接收服务端的反馈
            int len=0;
            while((len=sChannel.read(buffer))!=-1){
                buffer.flip();
                System.out.println(new String(buffer.array(),0,len));
                buffer.clear();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //5.关闭通道
            try {
                if(open!=null) {
                    open.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(sChannel!=null) {
                    sChannel.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    //服务端
    @Test
    public void server() {
        ServerSocketChannel open = null;
        FileChannel channel = null;
        SocketChannel accept = null;
        try {
             //1.获取通道
             open = ServerSocketChannel.open();
             //2.绑定连接
            open.bind(new InetSocketAddress(9999));
            //3.获取客户端连接的通道
            accept = open.accept();
            //4.分配指定大小的缓存区
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            //5.接受客户端的数据并保存到本地
            channel = FileChannel.open(Paths.get("5.jpg"), StandardOpenOption.WRITE, StandardOpenOption.CREATE);
            while (accept.read(buffer) != -1) {
                buffer.flip();
                channel.write(buffer);
                buffer.clear();
            }

            //6.发送反馈给客户端
            buffer.put("服务端接收数据成功".getBytes());
            buffer.flip();//给为读模式
            accept.write(buffer);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //7.关闭通道
            try {
                if(open!=null)
                    open.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(channel!=null)
                channel.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(accept!=null)
                    accept.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}
